﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GeoSketch2.Core;
using System.Drawing;

namespace GeoSketch2.Archaeo
{
    public class ArchaeoProject
    {
        /// <summary>
        /// The directory of the project
        /// </summary>
        public string ProjectDirectory;

        /// <summary>
        /// All objects of the site
        /// </summary>
        public List<BaseDrawableObject> ArchaeoObjects;

        /// <summary>
        /// All layers of the project
        /// </summary>
        public List<Layer> ProjectLayers;

        /// <summary>
        /// The list of all available linetypes for the project
        /// </summary>
        public List<LineType> LineTypeLibrary;

        /// <summary>
        /// The list of all the benchmarks of the site
        /// </summary>
        public List<Benchmark> SiteBenchmarks;

        /// <summary>
        /// The layer0 of the Site, this Layer is always present when creating a new square or unit
        /// </summary>
        public Layer Layer0;

        /// <summary>
        /// The default linetype
        /// </summary>
        public LineType DefaultLineType;

        /// <summary>
        /// The list of the archaeologists
        /// </summary>
        public List<string> ArchaeologistsList;

        public BaseSoilSheet SoilSheetModel;

        public ExcavationArea MainSite;

        public ArchaeoProject(BaseSoilSheet SoilSheetModel)
        {
            this.LineTypeLibrary = DefaultLineTypeLibrary;
            this.ProjectLayers = new List<Layer>();
            this.ArchaeologistsList = new List<string>();

            this.ArchaeoObjects = new List<BaseDrawableObject>();
            this.SiteBenchmarks = new List<Benchmark>();
            this.DefaultLineType = LineTypeLibrary[0];
            this.SoilSheetModel = SoilSheetModel;

            this.Layer0 = new Layer("Layer0", Color.Black, DefaultLineType, true);
            this.ProjectLayers.Add(Layer0);

            List<Layer> Layers = new List<Layer>();
            Layers.Add(Layer0);

            MainSite = new ExcavationArea("Site", "", DateTime.Now, DefaultSiteBounds, Layers, null, this);

        }

        public ArchaeoProject(List<LineType> LineTypeLibrary, List<Layer> ProjectLayers, List<string> ArchaeologistsList, Layer Layer0, BaseSoilSheet SoilSheetModel)
        {
            this.LineTypeLibrary = LineTypeLibrary;
            this.ProjectLayers = ProjectLayers;
            this.ArchaeologistsList = ArchaeologistsList;
            this.Layer0 = Layer0;

            this.ArchaeoObjects = new List<BaseDrawableObject>();
            this.SiteBenchmarks = new List<Benchmark>();
            this.DefaultLineType = LineTypeLibrary[0];
            this.SoilSheetModel = SoilSheetModel;
        }

        /// <summary>
        /// Gets a benchmark from its name
        /// </summary>
        public Benchmark GetBenchmarkFromName(string name)
        {
            foreach (Benchmark bm in SiteBenchmarks)
            {
                if (bm.Name == name)
                {
                    return bm;
                }
            }
            return null;
        }

        /// <summary>
        /// Gets an excavation unit from its name
        /// </summary>
        public ExcavationArea GetExcavationAreaFromName(string Name)
        {
            if (MainSite != null)
            {
                return GetExcavationAreaFromNameBrowseTree(MainSite, Name);
            }
            else
            {
                return null;
            }
        }

        ExcavationArea GetExcavationAreaFromNameBrowseTree(ExcavationArea Area, string Name)
        {
            ExcavationArea dst = null;

            if (Area.Name == Name) { dst = Area; }
            else
            {
                foreach (ExcavationArea a in Area.ChildrenExcavationAreas)
                {
                    dst = GetExcavationAreaFromNameBrowseTree(a, Name);
                    if (dst != null)
                    {
                        break;
                    }
                }
            }
            return dst;
        }

        /// <summary>
        /// Gets a Layer from its name
        /// </summary>
        public Layer GetLayerFromName(string name)
        {
            return this.ProjectLayers.Find(delegate(Layer l) { return l.Name == name; });
        }

        /// <summary>
        /// Gets a linetype from its id
        /// </summary>
        public LineType GetLineTypeFromId(int id)
        {
            return this.LineTypeLibrary.Find(delegate(LineType lt) { return lt.Id == id; });
        }

        /// <summary>
        /// Gets the default linetype library
        /// </summary>
        public static List<LineType> DefaultLineTypeLibrary
        {
            get
            {
                List<LineType> lib = new List<LineType>();
                lib.Add(new LineType(LineStyle.Solid));
                lib.Add(new LineType(LineStyle.Dot));
                lib.Add(new LineType(LineStyle.Dash));
                return lib;
            }
        }

        /// <summary>
        /// Gets the survey logbooks of the site
        /// </summary>
        public List<SurveyLogBook> SurveyLogBooks
        {
            get
            {
                return SurveyLogBooksBrowseTree(this.MainSite);
            }
        }

        List<SurveyLogBook> SurveyLogBooksBrowseTree(ExcavationArea Area)
        {
            List<SurveyLogBook> dst = new List<SurveyLogBook>();
            dst.Add(Area.SurveyLogBook);

            foreach (ExcavationArea a in Area.ChildrenExcavationAreas)
            {
                dst.AddRange(SurveyLogBooksBrowseTree(a));
            }

            return dst;
        }

        /// <summary>
        /// Saves the site to a file
        /// </summary>
        public void SaveToGSK(string Filename)
        {
            FileIO.WriteGSK(this, Filename);
        }

        /// <summary>
        /// Gets the default bounds of a new site
        /// </summary>
        public static Point2D64D[] DefaultSiteBounds
        {
            get
            {
                return new Point2D64D[]{
            new Point2D64D(-10000,-10000),
            new Point2D64D(-10000,10000),
            new Point2D64D(10000,10000),
            new Point2D64D(10000,-10000)};
            }
        }
    }
}
